const fs = require('fs-extra');
const path = require('path');
const utility = require('../../../utility');

const ParentReporter = require('./../default-report');
const ProjectVersionSpliter = require('./../../project-version-spliter');
const files = require('./../../../files');
const { mcdcKind } = require('./../../../tests');
const {
  generateStatemetBlocks,
  generateBranchBlocks,
  generateConditionBlocks,
  generateMcDcBlocks,
  generateCondMcDcBlocks,
  generateDecisionBlocks,
} = require('./../functionUtil');
const { versionType } = require('../../../project-versions');

class DefaultReporter extends ParentReporter {
  async handleFile(file, versionDir) {
    const reportPath = `${path.join(versionDir, path.dirname(file.path), file.fileName)}`;
    const res = await ProjectVersionSpliter.prototype.handleFile.call(this, file, versionDir);
    const { typeSystem, functions: funcs, resultCount } = res;
    if (!resultCount) {
      return Promise.resolve();
    }
    const fileContent = await files.getLinesOfRemoteFileStream(file._id, {});
    const linesInSourceFile = fileContent.map(({ content }) => content);
    await utility.arrayChunkOperation(funcs, 10, async (func) => {
      func.functionCfg = await this.getDataAdapter().getFunctionCfg(func);
    });
    if (this.willTestStatements()) {
      generateStatemetBlocks(funcs, linesInSourceFile);
    }
    if (this.willTestBranch()) {
      generateBranchBlocks(funcs, linesInSourceFile);
    }
    if (this.willTestCondition()) {
      generateConditionBlocks(funcs);
    }
    if (this.willTestDecision()) {
      generateDecisionBlocks(funcs, linesInSourceFile);
    }
    if (this.willTestMcdc()) {
      // 算法一
      if (this.version.mcdcKind === mcdcKind.masking) {
        generateMcDcBlocks(funcs);
      // 算法二
      } else {
        generateCondMcDcBlocks(funcs);
      }
    }
    funcs.map((func) => {
      func.codeCoverageDetails = [];
      if (this.willTestStatements()) {
        func.codeCoverageDetails.push(func.statementsBlocks);
      }
      if (this.willTestBranch() && func.branchTotal > 0) {
        func.codeCoverageDetails.push(func.branchBlocks);
      }
      if (this.willTestCondition() && func.conditionTotal > 0) {
        func.codeCoverageDetails.push(func.conditionsBlocks);
      }
      if (this.willTestDecision() && func.decisionTotal > 0) {
        func.codeCoverageDetails.push(func.decisionBlocks);
      }
      if (this.willTestMcdc() && func.mcdcTotal > 0) {
        func.codeCoverageDetails.push(func.mcdcBlocks || func.condMcdcBlocks);
      }
      return func;
    });
    await fs.ensureDir(path.dirname(reportPath));
    await this.generateFileReport(
      {
        fileName: file.fileName,
        summary: DefaultReporter.getSummaryOfFile(funcs),
        functions: this.getFunctionDetailsOfFile(typeSystem, funcs),
        isIntegrationTest: this.isIntegrationTest(),
        reportName: this.getReportName(),
        headerRightContent: `${this.getReportName()} - ${file.fileName}`,
      },
      reportPath
    );
    return { reportPath };
  }

  static versionTypeSupport(vType) {
    return vType === versionType.unitTest || vType === versionType.integrationTest;
  }
}

/**
 * Export model definition object.
 */
module.exports = DefaultReporter;
